package com.hc.comm.interceptor;


import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.hc.comm.annotation.Token;
import com.hc.comm.utils.ServletUtil;



/**
 * @ClassName: TockenInterceptor
 * @Description: 防止表单重复提交
 * @author 
 * @date 2014-8-27 下午4:36:11
 */
public class TokenInterceptor extends HandlerInterceptorAdapter {

	
	private static final String TOKEN = "token";
	
	/**
	 * 判断是否为同一次请求
	 */
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
            Object handler) throws Exception {
		//如果方法有@Token注解
		if(hasTokenMethod(handler)){
			//如果是重复提交
			if(sameRequest(request, response)){
				//调回原来的页面
				response.sendRedirect(request.getContextPath() + "/user/forwardLogin" + ServletUtil.getUrlStuff());
        		return false;
        	}
		}
		return super.preHandle(request, response, handler);
    }
	
	
	/**
	 * 请求到达页面之前，生成一个token并保存在request和session中
	 */
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		//如果是一次有页面渲染的请求，就给该页面生成Token
		if(modelAndView != null){
			String uuid = UUID.randomUUID().toString();
			request.setAttribute(TOKEN, uuid);
			ServletUtil.putSession(request, response, TOKEN, uuid);
		}
		super.postHandle(request, response, handler, modelAndView);
	}
	

	/**
	* @Title: sameRequest
	* @Description: 是否是同一个请求
	* @param  request
	* @return boolean 
	 */
	private boolean sameRequest(HttpServletRequest request, HttpServletResponse response){
    	//获取请求到达页面时生成的token
    	String clientToken = request.getParameter(TOKEN);
    	String serverToken = (String) ServletUtil.getSessionAttribute(request, response, TOKEN);
    	
    	//如果客户端或服务端没有token则不许提交
    	if(StringUtils.isBlank(clientToken) || StringUtils.isBlank(serverToken)){
    		return true;
    	}
    	//如果token不相同则提交表单，并且更新页面的token值
    	if(serverToken.equals(clientToken)){
    		return false;
    	}
    	
    	return true;
	}
	
	
	/**
	* @Title: hasTokenMethod
	* @Description: 判断是否是一个有@Token注解的方法
	* @param handler
	* @return boolean
	 */
	private boolean hasTokenMethod(Object handler){
		if(handler instanceof HandlerMethod){
			HandlerMethod handlerMethod = (HandlerMethod) handler;
            Token annotation = handlerMethod.getMethodAnnotation(Token.class);
            if(annotation!=null){
            	return true;
            }
		}
		return false;
	}
	
}
